home *** CD-ROM | disk | FTP | other *** search
Text File | 2006-02-18 | 38.0 KB | 1,209 lines |
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Forecastfox.
- *
- * The Initial Developer of the Original Code is
- * Jon Stritar <jstritar@MIT.EDU>.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Jon Stritar <jstritar@MIT.EDU>
- * Richard Klein <richwklein@mchsi.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
- /* XPCOM Constants */
- const CLASS_ID = Components.ID("{27e1bca0-aded-11d9-9669-0800200c9a66}");
- const CLASS_NAME = "Forecastfox Profiles Component";
- const CONTRACT_ID = "@ensolis.com/forecastfox/profiles;1";
- const nsIDOMXPathResult = Components.interfaces.nsIDOMXPathResult;
- const nsIFilePicker = Components.interfaces.nsIFilePicker;
- const ffIError = Components.interfaces.ffIError;
- const ffIProfiles = Components.interfaces.ffIProfiles;
- const ffIDisk = Components.interfaces.ffIDisk;
-
- /******************************************************************************
- * ffProfiles Component
- ******************************************************************************/
- function ffProfiles() { };
-
- ffProfiles.prototype = {
- _batch: false,
- _current: null,
- _doc: null,
- _manager: null,
- _loading: false,
- _rotating: false,
- _prefs: null,
- _xpath: null,
- _xresolve: null,
- _obs: null,
- _default: null,
- _timer: null,
- _bundle: null,
-
- get batch() { return this._batch; },
-
- get current() {
- if (!this._current)
- return "";
-
- return this._current;
- },
-
- get document() { return this._doc },
- set document(aValue) {
- this._doc = aValue;
- var file = this._manager.disk.get("profiles.xml", ffIDisk.TYPE_CACHE);
- this._manager.disk.write(this._doc, file);
- },
-
- start: function()
- {
- this._loading = true;
-
- //set up components
- this._xpath = Components.classes["@mozilla.org/dom/xpath-evaluator;1"].getService(Components.interfaces.nsIDOMXPathEvaluator);
- this._xresolve = Components.classes["@ensolis.com/forecastfox/resolver;1"].createInstance(Components.interfaces.nsIDOMXPathNSResolver);
- this._obs = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
- this._manager = Components.classes["@ensolis.com/forecastfox/manager;1"].getService(Components.interfaces.ffIManager);
- this._timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
- var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
- this._bundle = sbs.createBundle("chrome://forecastfox/locale/forecastfox.properties");
- var pbs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
- this._default = pbs.getDefaultBranch("forecastfox.");
-
- //load preference names from the default file
- this._prefs = this._getPrefs();
-
- //load and migrate data
- var error = this._loadDoc();
-
- //start rotating
- if (error.severity != ffIError.SEVERITY_ERROR)
- this.rotate(ffIProfiles.ROTATE_START);
-
- this._loading = false;
- return error;
- },
-
- stop: function()
- {
- //save the current profile
- this.save(this._current);
-
- //cancel timer
- this._timer.cancel();
-
- //destroy variables
- this._batch = null;
- this._current = null;
- this._doc = null;
- this._manager = null;
- this._loading = null;
- this._rotating = null;
- this._prefs = null;
- this._xpath = null;
- this._xresolve = null;
- this._obs = null;
- this._default = null;
- this._timer = null;
- this._bundle = null;
- },
-
- load: function(aName)
- {
- this._batch = true;
- this.rotate(ffIProfiles.ROTATE_STOP);
- this._manager.cancel();
-
- //save the current profile
- this.save(this._current, true);
-
- //get profile
- var profiles = this._evalPath(this._doc, "//profiles");
- var profile = this._evalPath(profiles, "./profile[@id='" + aName + "']");
-
- //load preferences
- for (var x=0; x<this._prefs.length; x++) {
- var pref = this._evalPath(profile, "./pref[@name='" + this._prefs[x] + "']");
- this._setPref(pref);
- };
-
- //set current
- this._current = aName;
-
- //notify complete
- this._batch = false;
- if (!this._loading) {
- this._obs.notifyObservers(this, "forecastfox:profile", aName);
- this.rotate(ffIProfiles.ROTATE_START);
- }
- },
-
- save: function(aName, aTest)
- {
- //return if nothing passed
- if (!aName)
- return;
-
- //test if a valid profile
- if (!this._isProfile(aName) && aTest)
- return;
-
- var profiles = this._evalPath(this._doc, "//profiles");
- var profile = this._evalPath(profiles, "./profile[@id='" + aName + "']");
-
- //check if this is a new profile
- if (profile)
- profile.parentNode.removeChild(profile);
-
- //create profile
- profile = this._doc.createElement("profile");
- profile.setAttribute("id", aName);
-
- //add preference to it
- var pref, type;
- for (var x=0; x<this._prefs.length; x++) {
- type = this._getPrefType(this._prefs[x], false);
- pref = this._doc.createElement("pref");
- pref.setAttribute("name", this._prefs[x]);
- pref.setAttribute("type", type);
- pref.setAttribute("value", eval("this._manager.branch.get" + type + "Pref('" + this._prefs[x] + "')"));
- profile.appendChild(pref);
- };
-
- //append profile to profiles
- profiles.appendChild(profile);
-
- //flush to disk
- var file = this._manager.disk.get("profiles.xml", ffIDisk.TYPE_CACHE);
- this._manager.disk.write(this._doc, file, true);
- },
-
- rotate: function(aRotate)
- {
- //cancel in timers
- this._timer.cancel();
-
- //stop rotating
- if (aRotate == ffIProfiles.ROTATE_STOP)
- this._rotating = false;
- else {
- this._rotating = true;
- this._schedule();
- }
- },
-
- create: function(aName)
- {
- this._batch = true;
- this.rotate(ffIProfiles.ROTATE_STOP);
- this._manager.cancel();
-
- //make sure profile is saved
- this.save(this._current, true);
-
- //clone the current profile
- var name = this._stripName(aName);
- var profiles = this._evalPath(this._doc, "//profiles");
- var profile = this._evalPath(profiles, "./profile[@id='" + this._current + "']");
- if (!profile)
- profile = this._doc.createElement("profile");
- var to = profile.cloneNode(true);
-
- //set id
- to.setAttribute("id", name);
-
- //copy cache
- this._cacheFiles(profile, to, false);
- this._cachePrefs(profile, to);
-
- //append
- profiles.appendChild(to);
-
- //set current pref which will
- //load this one and flush data to disk
- this._batch = false;
- this.rotate(ffIProfiles.ROTATE_START);
- this._manager.setUTFPref("profile.current", name);
- },
-
- rename: function(aName, aTo)
- {
- this._batch = true;
- this.rotate(ffIProfiles.ROTATE_STOP);
- this._manager.cancel();
-
- //make sure profile is saved
- this.save(this._current, true);
-
- //clone the from profile
- var name = this._stripName(aTo);
- var profiles = this._evalPath(this._doc, "//profiles");
- var profile = this._evalPath(profiles, "./profile[@id='" + aName + "']");
- var to = profile.cloneNode(true);
-
- //set id
- to.setAttribute("id", name);
-
- //copy cache
- this._cacheFiles(profile, to, true);
- this._cachePrefs(profile, to);
-
- //append
- profiles.appendChild(to);
-
- //remove from
- profiles.removeChild(profile);
-
- //set current pref which will
- //load this one and flush data to disk
- this._current = null;
- this._batch = false;
- this.rotate(ffIProfiles.ROTATE_START);
- this._manager.setUTFPref("profile.current", name);
- },
-
- remove: function(aName, aTo)
- {
- this._batch = true;
- this.rotate(ffIProfiles.ROTATE_STOP);
- this._manager.cancel();
-
- //make sure profile is saved
- this.save(this._current, true);
-
- //get the from profile
- var profiles = this._evalPath(this._doc, "//profiles");
- var profile = this._evalPath(profiles, "./profile[@id='" + aName + "']");
-
- //delete cache files
- this._cacheFiles(profile, null, true);
-
- //remove from
- profiles.removeChild(profile);
-
- //set current pref which will
- //load this one and flush data to disk
- this._current = null;
- this._batch = false;
- this.rotate(ffIProfiles.ROTATE_START);
- this._manager.setUTFPref("profile.current", aTo);
- },
-
- getProfileNum: function()
- {
- var profiles = this._evalPath(this._doc, "//profiles");
- profiles = profiles.getElementsByTagName("profile");
- return profiles.length;
- },
-
- getProfile: function(aIndex)
- {
- var profiles = this._evalPath(this._doc, "//profiles");
- var val = new Array();
- profiles = profiles.getElementsByTagName("profile");
- return profiles[aIndex].getAttribute("id");
- },
-
- open: function(aOpen, aWindow)
- {
- //set variables
- var alerts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
-
- //get file
- var file = this._filePicker(aOpen, aWindow);
- if (!file)
- return;
-
- //do import-export
- switch (aOpen) {
- case ffIProfiles.OPEN_EXPORT:
- this._export(alerts, aWindow, file);
- break;
- case ffIProfiles.OPEN_IMPORT:
- this._import(alerts, aWindow, file);
- break;
- }
- },
-
- _loadDoc: function()
- {
- this._batch = true;
- var from = this._manager.branch.getCharPref("migrated");
- var previous = this._manager.branch.prefHasUserValue("migrated");
- var file = this._manager.disk.get("profiles.xml", ffIDisk.TYPE_CACHE);
- var exists = file.exists();
-
- //do simple load
- if (previous)
- return this._simpleLoad(from, file);
-
- //do complex load
- return this._complexLoad(from, file, exists);
- },
-
- _simpleLoad: function(aFrom, aFile)
- {
- // completes the uninstallation/upgrade of weatherfox
- if (aFrom == "*") {
- var pbs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService)
- var branch = pbs.getBranch("weatherfox.");
- branch.deleteBranch("");
- this._manager.disk.remove(ffIDisk.TYPE_WEATHERFOX);
- };
-
- //get profile document
- var error = this._getDoc(aFile);
- if (error.severity != ffIError.SEVERITY_INFO)
- return error;
- if (!this._doc)
- return this._createError(ffIError.SEVERITY_ERROR, "ff.migrate", null, null);
-
- //determine from version
- var from = this._evalPath(this._doc, "//@version");
- if (from)
- from = from.textContent;
- else
- from = aFrom;
-
- //do transforms
- var doc = this._transform(this._doc, from);
- if (!doc) {
- this._doc = null;
- return this._createError(ffIError.SEVERITY_ERROR, "ff.transform", null, null);
- } else
- this._doc = doc;
-
- //clear icons if before 0.8.5
- try {
- var vchecker = Components.classes["@mozilla.org/updates/version-checker;1"].getService(Components.interfaces.nsIVersionChecker);
- var compare = vchecker.compare(from, "0.8.5");
- } catch(e) {
- try {
- vchecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"].getService(Components.interfaces.nsIVersionComparator);
- } catch(e) {
- vchecker = null;
- };
- compare = (from < "0.8.5") ? -1 : 0;
- };
- if (compare < 0)
- this._manager.disk.clear(ffIDisk.TYPE_ICONS, false);
-
- //finalize migration
- this._finishLoad(aFile, "0.8.5");
- return this._createError(ffIError.SEVERITY_INFO, null, "", "");
- },
-
- _complexLoad: function(aFrom, aFile, aExists)
- {
- //determine if we are in toolkit
- var isToolkit = true;
- try {
- var em = Components.classes["@mozilla.org/extensions/manager;1"].getService(Components.interfaces.nsIExtensionManager);
- } catch (e) {
- isToolkit = false;
- };
-
- //non toolkit version
- if (!isToolkit)
- return this._nonToolkitLoad(aFrom, aFile, aExists);
-
- //toolkit version
- //determine if we are coming from weatherfox
- var isWeatherfox = false;
- var weatherfox = new Array();
- try {
- weatherfox[0] = em.getItemForID("{BA8E053E-2867-4772-B9F0-26A5979AFA09}");
- isWeatherfox = (weatherfox[0].location != null);
- } catch(e) {
- weatherfox = em.getItemList("{BA8E053E-2867-4772-B9F0-26A5979AFA09}", Components.interfaces.nsIUpdateItem.TYPE_EXTENSION, {});
- isWeatherfox = (weatherfox[0] != null);
- };
-
- //not weatherfox
- if (!isWeatherfox)
- return this._toolkitLoad(aFrom, aFile, aExists);
-
- //is weatherfox
- return this._weatherfoxLoad(aFrom, aFile, aExists, em, weatherfox);
- },
-
- _nonToolkitLoad: function(aFrom, aFile, aExists)
- {
- //get profile document
- var error = this._getDoc(aFile);
- if (error.severity != ffIError.SEVERITY_INFO)
- return error;
- if (!this._doc)
- return this._createError(ffIError.SEVERITY_WARNING, "ff.migrate", null, null);
-
- // bug in version 0.7.0 and 0.7.1 for non toolkit did not update migrate pref
- // so manually override it here if its null
- var doc;
- if (aExists && aFrom == "")
- doc = this._transform(this._doc, "0.7.1");
- else
- doc = this._doc;
- if (!doc) {
- this._doc = null;
- return this._createError(ffIError.SEVERITY_ERROR, "ff.transform", null, null);
- } else
- this._doc = doc;
-
- //finalize migration
- this._finishLoad(aFile, "0.8.5");
- return this._createError(ffIError.SEVERITY_INFO, null, "", "");
- },
-
- _toolkitLoad: function(aFrom, aFile, aExists)
- {
- //get profile document
- var error = this._getDoc(aFile);
- if (error.severity != ffIError.SEVERITY_INFO)
- return error;
- if (!this._doc)
- return this._createError(ffIError.SEVERITY_WARNING, "ff.migrate", null, null);
-
- //has to be either 0.5.8 or 0.5.9
- //so error on lower side or doesn't exist
- var doc;
- if (aExists)
- doc = this._transform(this._doc, "0.5.8");
- else
- doc = this._doc;
- if (!doc) {
- this._doc = null;
- return this._createError(ffIError.SEVERITY_ERROR, "ff.transform", null, null);
- } else
- this._doc = doc;
-
- //finalize migration
- this._finishLoad(aFile, "0.8.5");
- return this._createError(ffIError.SEVERITY_INFO, null, "", "");
- },
-
- _weatherfoxLoad: function(aFrom, aFile, aExists, aEM, aWeatherfox)
- {
- //get profile document
- var error = this._getDoc(aFile);
- if (error.severity != ffIError.SEVERITY_INFO)
- return error;
- if (!this._doc)
- return this._createError(ffIError.SEVERITY_WARNING, "ff.migrate", null, null);
-
- //can't transform a version before 0.4.8
- try {
- var vchecker = Components.classes["@mozilla.org/updates/version-checker;1"].getService(Components.interfaces.nsIVersionChecker);
- } catch(e) {
- vchecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"].getService(Components.interfaces.nsIVersionComparator);
- };
-
- if (vchecker.compare(aWeatherfox[0].version, "0.4.8") < 0)
- return this._createError(ffIError.SEVERITY_ERROR, "ff.migrate.version", null, null);
-
- //transform the weatherfox profile
- var wfile = this._manager.disk.get("profiles.xml", ffIDisk.TYPE_WEATHERFOX);
- if (wfile.exists() && wfile.isReadable()) {
- var wDoc = this._manager.disk.read(wfile);
- if (this._manager.disk.valid(wDoc)) {
- var doc = this._transform(wDoc, aWeatherfox[0].version);
- if (!doc)
- return this._createError(ffIError.SEVERITY_ERROR, "ff.transform", null, null);
- else
- this._doc = doc;
-
- //set current profile
- var pbs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService)
- var branch = pbs.getBranch("weatherfox.");
- this._manager.setUTFPref("profile.current", branch.getCharPref("profile"));
- };
- };
-
- //remove weatherfox from em
- try {
- // use this 1.1 and on
- aEM.uninstallItem("{BA8E053E-2867-4772-B9F0-26A5979AFA09}");
- } catch (e) {
- // use this through 1.0
- aEM.uninstallExtension("{BA8E053E-2867-4772-B9F0-26A5979AFA09}");
- };
-
- //finalize migration
- this._finishLoad(aFile, "*");
- if (error.severity != ffIError.SEVERITY_ERROR)
- return this._createError(ffIError.SEVERITY_WARNING, "ff.migrate.restart", null, null);
- else
- return error;
- },
-
- _finishLoad: function(aFile, aVersion)
- {
- this._manager.disk.write(this._doc, aFile, true);
- this._manager.branch.setCharPref("migrated", aVersion);
-
- //XXX seems like there may be some redundancy in here, there
- // could there be any synchronization problems too?
- var profile;
- if (!this._isProfile(this._manager.getUTFPref("profile.current"))) {
- profile = this._manager.getUTFPref("profile.current");
- this.create(profile);
- };
- profile = this._firstProfile();
-
- //complete migration by setting the migrated prefs
- var profiles = this._evalPath(this._doc, "//profiles");
- var profileNode = this._evalPath(profiles, "./profile[@id='" + profile + "']");
-
- for (var x=0; x<this._prefs.length; x++) {
- var pref = this._evalPath(profile, "./pref[@name='" + this._prefs[x] + "']");
- this._setPref(pref);
- };
-
- this._current = profile;
-
- this._batch = false;
- },
-
- _getDoc: function(aFile)
- {
- var backup = this._manager.disk.get("profiles.bak", ffIDisk.TYPE_CACHE);
- var doc = null;
-
- //try loading profile file first
- if (aFile.exists()) {
- if (!aFile.isReadable() || !aFile.isWritable()) {
- this._doc = null;
- var err_tool = this._bundle.formatStringFromName("ff.migrate.read.tooltip", [aFile.path], 1);
- var err_label = this._bundle.GetStringFromName("ff.migrate.read.label");
- return this._createError(ffIError.SEVERITY_ERROR, null, err_label, err_tool);
- };
- doc = this._manager.disk.read(aFile);
- if (this._manager.disk.valid(doc)) {
- this._doc = doc;
- return this._createError(ffIError.SEVERITY_INFO, null, "", "");
- } else
- this._manager.disk.recordFile(aFile);
- } else
- this._manager.disk.recordMessage("Message: Expected profiles.xml, but was missing.");
-
- //try loading backup
- if (backup.exists() && backup.isReadable()) {
- doc = this._manager.disk.read(backup);
- if (this._manager.disk.valid(doc)) {
- this._doc = doc;
- return this._createError(ffIError.SEVERITY_INFO, null, "", "");
- } else
- this._manager.disk.recordFile(backup);
- } else
- this._manager.disk.recordMessage("Message: Expected backup profiles.xml, but was missing.");
-
- //create default profiles document
- doc = this._createDefault();
- this._manager.disk.clear(ffIDisk.TYPE_CACHE, true);
- this._doc = doc;
- return this._createError(ffIError.SEVERITY_INFO, "ff.migrate.default", null, null);
- },
-
- _createDefault: function()
- {
- //create empty document
- var contents = new String();
- var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
- contents += '<?xml version="1.0"?>\n' +
- '<profiles version="0.8.5">\n' +
- '</profiles>\n'
- var doc = parser.parseFromString(contents, "text/xml");
-
- //create default profile node
- var profiles = doc.getElementsByTagName("profiles")[0];
- var profile = doc.createElement("profile");
- profile.setAttribute("id", "default");
- profiles.appendChild(profile);
-
- //add preferences
- var pref, type;
- for (var x=0; x<this._prefs.length; x++) {
- type = this._getPrefType(this._prefs[x], true);
- pref = doc.createElement("pref");
- pref.setAttribute("name", this._prefs[x]);
- pref.setAttribute("type", type);
- try {
- pref.setAttribute("value", eval("this._default.get" + type + "Pref('" + this._prefs[x] + "')"));
- } catch(e) {
- switch (type) {
- case "Char":
- pref.setAttribute("value", "");
- break;
- case "Int":
- pref.setAttribute("value", "0");
- break;
- case "Bool":
- pref.setAttribute("value", "false");
- break;
- };
- };
- profile.appendChild(pref);
- };
-
- //return created document
- return doc;
- },
-
- _transform: function(aDoc, aFrom)
- {
- var processor = Components.classes["@mozilla.org/document-transformer;1?type=xslt"].createInstance(Components.interfaces.nsIXSLTProcessor);
- var from = aFrom;
-
- //use version checker if possible
- try {
- var vchecker = Components.classes["@mozilla.org/updates/version-checker;1"].getService(Components.interfaces.nsIVersionChecker);
- var compare = vchecker.compare(from, "0.8.5");
- } catch(e) {
- try {
- vchecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"].getService(Components.interfaces.nsIVersionComparator);
- } catch(e) {
- vchecker = null;
- };
- compare = (from < "0.8.5") ? -1 : 0;
- };
-
- //loop up through version
- while (compare < 0) {
-
- //invalid document
- if (!this._manager.disk.valid(aDoc)) {
- return null;
- };
-
- //load the stylesheet
- var sheet = this._manager.disk.get("profiles-" + from + ".xsl", ffIDisk.TYPE_TRANSFORMS);
- if (!sheet.exists() || !sheet.isReadable()) {
- return null;
- };
-
- //invalid stylesheet
- var sdoc = this._manager.disk.read(sheet);
- if (!this._manager.disk.valid(sdoc)) {
- return null;
- };
-
- //transform document
- processor.reset();
- processor.importStylesheet(sdoc);
- var frag = processor.transformToFragment(aDoc.getElementsByTagName("profiles")[0], aDoc);
- aDoc.replaceChild(frag.firstChild, aDoc.getElementsByTagName("profiles")[0]);
-
- //get version doc was transformed to
- var node = this._evalPath(aDoc, "//@version");
- if (!node) {
- return null;
- } else
- from = node.textContent;
-
- if (vchecker) {
- compare = vchecker.compare(from, "0.8.5");
- } else {
- compare = (from < "0.8.5") ? -1 : 0;
- };
- };
-
- return aDoc;
- },
-
- _import: function(aAlerts, aWindow, aFile)
- {
- //load import file
- if (!aFile.exists()) {
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.import"), this._bundle.GetStringFromName("ff.import.document"));
- return;
- };
- if (!aFile.isReadable()) {
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.import"), this._bundle.GetStringFromName("ff.import.read"));
- return;
- };
- var doc = this._manager.disk.read(aFile);
- if (!this._manager.disk.valid(doc)) {
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.import"), this._bundle.GetStringFromName("ff.import.document"));
- return;
- };
-
- //have current and profiles
- var profiles = doc.getElementsByTagName("profiles")[0];
- if (!profiles) {
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.import"), this._bundle.GetStringFromName("ff.import.invalid"));
- return;
- };
-
- //get version we are importing from
- var version = this._evalPath(doc, "//@version");
- if (!version) {
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.import"), this._bundle.GetStringFromName("ff.import.invalid"));
- return;
- } else
- version = version.textContent;
-
- //get profiles node in current doc
- //and replace with profiles node in import doc
- var cDoc = this._doc.cloneNode(true);
- var node = this._evalPath(cDoc, "//profiles");
- var parent = node.parentNode;
- parent.removeChild(node);
- parent.appendChild(profiles.cloneNode(true));
-
- //tranform document
- cDoc = this._transform(cDoc, version);
- if (!cDoc) {
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.import"), this._bundle.GetStringFromName("ff.transform.tooltip"));
- return;
- };
-
- //flush data to disk
- var file = this._manager.disk.get("profiles.xml", ffIDisk.TYPE_CACHE);
- this._manager.disk.write(cDoc, file, true);
-
- //load profile
- this._current = null;
- this._doc = cDoc;
-
- if (this._manager.getUTFPref("profile.current") == this._firstProfile())
- this.load(this._firstProfile());
- else
- this._manager.setUTFPref("profile.current", this._firstProfile());
-
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.import"), this._bundle.GetStringFromName("ff.import.success"));
- },
-
- _export: function(aAlerts, aWindow, aFile)
- {
- //create content string of file
- var contents = new String();
- contents += '<?xml version="1.0"?>\n' +
- '<forecastfox-settings>\n' +
- '</forecastfox-settings>\n'
-
- //convert to dom document
- var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
- var doc = parser.parseFromString(contents, "text/xml");
-
- //copy profiles to export document
- var profiles = this._evalPath(this._doc, "//profiles");
- var node = doc.getElementsByTagName("forecastfox-settings")[0];
- node.appendChild(profiles.cloneNode(true));
-
- //flush to disk
- if (aFile.exists() && !aFile.isWritable()) {
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.export"), this._bundle.GetStringFromName("ff.export.write"));
- return;
- };
-
- //finished
- this._manager.disk.write(doc, aFile, false);
- aAlerts.alert(aWindow, this._bundle.GetStringFromName("ff.export"), this._bundle.GetStringFromName("ff.export.success"));
- },
-
- _firstProfile: function()
- {
- //current profile set and valid
- var profile = this._current;
- if (profile && this._isProfile(profile))
- return profile;
-
- //preference set and valid
- profile = this._manager.getUTFPref("profile.current");
- if (profile && this._isProfile(profile))
- return profile;
-
- //default profile exists
- profile = "default";
- if (profile && this._isProfile(profile))
- return profile;
-
- //grab first profile available
- profile = this._doc.getElementsByTagName("profile")[0].getAttribute("id");
- if (profile && this._isProfile(profile))
- return profile;
-
- return null;
- },
-
- _createError: function(aSeverity, aName, aDescription, aTooltip)
- {
- var description = (aName) ? this._bundle.GetStringFromName(aName + ".label") : aDescription;
- var tooltip = (aName) ? this._bundle.GetStringFromName(aName + ".tooltip") : aTooltip;
- var error = Components.classes["@ensolis.com/forecastfox/error;1"].createInstance(Components.interfaces.ffIError);
- error.init(aSeverity, "@ensolis.com/forecastfox/profiles;1", description, tooltip);
- return error;
- },
-
- _filePicker: function(aOpen, aWindow)
- {
- var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
- picker.appendFilters(nsIFilePicker.filterXML);
- picker.defaultExtension = ".xml";
- switch (aOpen) {
- case ffIProfiles.OPEN_EXPORT:
- picker.init(aWindow, this._bundle.GetStringFromName("ff.export"), nsIFilePicker.modeSave);
- break;
- case ffIProfiles.OPEN_IMPORT:
- picker.init(aWindow, this._bundle.GetStringFromName("ff.import"), nsIFilePicker.modeOpen);
- break;
- };
-
- // get the file and its contents
- var res = picker.show();
- if (res == nsIFilePicker.returnCanel)
- return null;
- else
- return picker.file;
- },
-
- _isProfile: function(aName)
- {
- var profile = this._evalPath(this._doc, "//profiles/profile[@id='"+aName+"']");
- return (profile != null);
- },
-
- _schedule: function()
- {
- if (!this._rotating)
- this.rotate(ffIProfiles.ROTATE_STOP);
- else {
- //see if we have multiple profiles
- var profiles = this._evalPath(this._doc, "//profiles");
- if (profiles.getElementsByTagName("profile").length <= 1)
- return;
-
- var rotate = this._manager.branch.getBoolPref("profile.switch.enabled");
- var rotateTime = this._manager.branch.getIntPref("profile.switch.delay");
-
- //bail out if its disabled
- if (rotate == false || rotateTime <= 0)
- return;
-
- rotateTime *= 1000 * 60;
-
- // then schedule the timer
- this._timer.initWithCallback(this, rotateTime, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
- }
- },
-
- _encodeValue: function(aValue)
- {
- // only encode the strings
- if (typeof aValue != "string")
- return aValue;
-
- // prepare the quotes so that we can use eval
- return aValue.replace(/"/g,"\\\"").replace(/'/g,"\\\'");
- },
-
- _setPref: function(aNode)
- {
- if (!aNode)
- return;
-
- //get variables
- var pref = aNode.getAttribute("name");
- var type = aNode.getAttribute("type");
- var value = aNode.getAttribute("value");
-
- //set value based on type
- if (type == "Bool")
- value = (value == "true") ? true : false;
- else if (type == "Int")
- value = Number(value);
- else if (type == "Char")
- value = value
-
- //get the old value
- var oldValue = null;
- var defaultValue = null;
- var hasValue = false;
-
- try {
- oldValue = eval("this._manager.branch.get" + type + "Pref('" + pref + "')");
- defaultValue = eval("this._default.get" + type + "Pref('" + pref + "')");
- hasValue = eval("this._manager.branch.prefHasUserValue('" + pref + "')");
- } catch(e) {};
-
- //do nothing if the same value
- if (value == oldValue)
- return;
-
- //clear if same as default value
- if (value == defaultValue && hasValue)
- eval("this._manager.branch.clearUserPref('" + pref + "')");
- else {
- if (type == "Char")
- value = '"' + this._encodeValue(value) + '"';
- eval("this._manager.branch.set" + type + "Pref('" + pref + "', " + value + ")");
- }
- },
-
- _getPrefType: function(aName, aDefault)
- {
- //convert integer type to character type
- var type;
- if (!aDefault)
- type = this._manager.branch.getPrefType(aName);
- else
- type = this._default.getPrefType(aName);
-
- var val = null;
- switch (type) {
- case 0:
- val = "";
- break;
- case 32:
- default:
- val = "Char";
- break;
- case 64:
- val = "Int";
- break;
- case 128:
- val = "Bool";
- break;
- };
-
- return val;
- },
-
- _evalPath: function(aNode, aExpr)
- {
- var result = null;
-
- try {
- var results = this._xpath.evaluate(aExpr, aNode, this._xresolve, nsIDOMXPathResult.ANY_TYPE, null);
- result = results.iterateNext();
- } catch(e) {};
-
- return result;
- },
-
- _cacheFiles: function(aFrom, aTo, aDelete)
- {
- var folder = this._manager.disk.get("", ffIDisk.TYPE_CACHE);
- var i, to, name;
- var fName = "";
- var tName = "";
-
- //get names
- fName = aFrom.getAttribute("id");
- if (aTo)
- tName = aTo.getAttribute("id");
-
- //get a list of cache files
- var entries = folder.directoryEntries;
- var files = new Array();
- while (entries.hasMoreElements()) {
- var entry = entries.getNext();
- entry = entry.QueryInterface(Components.interfaces.nsIFile);
- name = entry.leafName;
-
- //make sure its a cache file
- if (name.indexOf("cache") == -1)
- continue;
-
- //make sure it is a from cache
- if (name.indexOf(fName) != -1)
- files.push(entry);
- };
-
- //now loop through our files
- for (i=0; i<files.length; i++) {
-
- //get to file
- if (aTo) {
- to = folder.clone();
- name = files[i].leafName;
- name = name.replace(fName, tName);
- to.append(name);
- if (files[i].exists()) {
- if (aDelete)
- this._manager.disk.move(files[i], to);
- else
- this._manager.disk.copy(files[i], to);
- }
- };
- }
- },
-
- _cachePrefs: function(aFrom, aTo)
- {
- //get a list of preferences
- var nodes = new Object();
-
- //loop through prefs finding cache prefs
- for (var i=0; i<this._prefs.length; i++) {
- if (this._prefs[i].indexOf("cache") == -1)
- continue;
-
- //get profile node that matches
- nodes[this._prefs[i]] = this._evalPath(aTo, "./pref[@name='" + this._prefs[i] + "']");
- };
-
- //replace value and update
- //pref may not exist if we migrated so wrap in try catch
- var fName = aFrom.getAttribute("id");
- var tName = aTo.getAttribute("id");
- for (j in nodes) {
- try {
- var value = nodes[j].getAttribute("value");
- value = value.replace(fName, tName);
- nodes[j].setAttribute("value", value);
- } catch (e) {};
- }
- },
-
- _getPrefs: function()
- {
- var excludes = new Object();
- excludes["migrated"] = true;
- excludes["pinged"] = true;
- excludes["icons.version"] = true;
- excludes["schedule.bump"] = true;
- excludes["schedule.span"] = true;
- excludes["profile.current"] = true;
- excludes["icons.uninstallfiles"] = true;
- var defaults = this._default.getChildList("", {});
- var prefs = new Array();
-
- for (var i=0; i<defaults.length; i++) {
- if (excludes[defaults[i]])
- continue;
- prefs.push(defaults[i]);
- };
-
- return prefs;
- },
-
- _stripName: function(name)
- {
- // remove illegal characters
- return name.replace(/[\\\/:*?<>|\'\"]/g, "");
- },
-
- ///////////////////////////
- // nsITimerCallback
- notify: function(timer)
- {
- var profiles = this._evalPath(this._doc, "//profiles");
- profiles = profiles.getElementsByTagName("profile");
-
- // go to next profile in the list
- for (var x=0; x<profiles.length; x++) {
- if (profiles[x].getAttribute("id") == this._current) {
- this._manager.setUTFPref("profile.current", profiles[( x+1 < profiles.length ) ? x+1 : 0 ].getAttribute("id"));
- break;
- };
- };
-
- //schedule rotation
- this._schedule();
- },
-
- ///////////////////////////
- // nsIClassInfo
- getInterfaces: function(aCount)
- {
- var ifaces = new Array();
- ifaces.push(Components.interfaces.ffIProfiles);
- ifaces.push(Components.interfaces.nsITimerCallback);
- ifaces.push(Components.interfaces.nsIClassInfo);
- ifaces.push(Components.interfaces.nsISupports);
- aCount.value = ifaces.length;
- return ifaces;
- },
-
- getHelperForLanguage: function(aLanguage) { return null; },
- get contractID() { return CONTRACT_ID; },
- get classID() { return CLASS_ID; },
- get classDescription() { return CLASS_NAME; },
- get implementationLanguage() { return Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT; },
- get flags() { return Components.interfaces.nsIClassInfo.SINGLETON; },
-
- ///////////////////////////
- // nsISupports
- QueryInterface: function (aIID)
- {
- if (!aIID.equals(Components.interfaces.ffIProfiles) &&
- !aIID.equals(Components.interfaces.nsITimerCallback) &&
- !aIID.equals(Components.interfaces.nsIClassInfo) &&
- !aIID.equals(Components.interfaces.nsISupports))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- }
- };
-
- /******************************************************************************
- * XPCOM Functions for construction and registration
- ******************************************************************************/
- var gModule = {
- _firstTime: true,
- registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
- {
- if (this._firstTime) {
- this._firstTime = false;
- throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
- };
- aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
- aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
- },
-
- unregisterSelf: function(aCompMgr, aLocation, aType)
- {
- aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
- aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);
- },
-
- getClassObject: function(aCompMgr, aCID, aIID)
- {
- if (!aIID.equals(Components.interfaces.nsIFactory))
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- if (aCID.equals(CLASS_ID))
- return gFactory;
-
- throw Components.results.NS_ERROR_NO_INTERFACE;
- },
-
- canUnload: function(aCompMgr) { return true; }
- };
-
- var gFactory = {
- createInstance: function (aOuter, aIID)
- {
- if (aOuter != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- return (new ffProfiles()).QueryInterface(aIID);
- }
- };
-
- function NSGetModule(aCompMgr, aFileSpec) { return gModule; }